import Entity.ClassEntity;
import Entity.FieldEntity;
import Entity.MethodEntity;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * java源代码分析器, 读入java源代码文件，生成类型结构
 */
class ClassAnalyzer {

    private MyClassLoader myClassLoader = new MyClassLoader();

    private final Map<String, Class<?>> classMaps = new HashMap<>();

    public ClassEntity parseJavaFile(String filePath, String className) throws MalformedURLException, ClassNotFoundException {

        Class<?> clazz = myClassLoader.findClass(filePath, className);
        if (null == clazz) {
            return null;
        }
        ClassEntity classEntity = new ClassEntity(className);
        //解析成员变量
        Field[] fields = clazz.getDeclaredFields();
        Arrays.stream(fields).forEach(e -> {
            FieldEntity field = new FieldEntity(e.getName(), e.getType().getSimpleName());
            classEntity.addField(field);
        });
        //解析方法
        Method[] methods = clazz.getDeclaredMethods();
        Arrays.stream(methods).forEach(e -> {
            MethodEntity method = new MethodEntity(e.getName(),
                    e.getReturnType().getSimpleName(),
                    "public",
                    Arrays.stream(e.getParameterTypes()).map(Class::getSimpleName).collect(Collectors.toList()),
                    false);
            classEntity.addMethod(method);
        });
        return classEntity;
    }


    /**
     * 加载目录下的所有class文件，将其解析成java类
     * @param dir 将要加载的目录
     */
    public void loadClassFromDir(String dir) {
        if (null == dir || dir.isBlank()) {
            System.out.println("empty path");
            return;
        }
        File home = new File(dir);
        String[] files = home.list();
        assert files != null;
        Arrays.stream(files).forEach(file -> {
            String classPath = String.format("file://%s/%s",dir, file);
            String className = file.replace(".class", "");
            Class<?> clazz = myClassLoader.findClass(classPath, className);
            classMaps.put(className, clazz);
        });
    }

    public List<ClassEntity> getClassEntities() {
        List<ClassEntity> classEntities = new ArrayList<>();
        classMaps.forEach((className, clazz) -> {
            ClassEntity classEntity = new ClassEntity(className);
            //解析成员变量
            Field[] fields = clazz.getDeclaredFields();
            Arrays.stream(fields).forEach(e -> {
                FieldEntity field = new FieldEntity(e.getName(), e.getType().getSimpleName());
                classEntity.addField(field);
            });
            //解析方法
            Method[] methods = clazz.getDeclaredMethods();
            Arrays.stream(methods).forEach(e -> {
                //忽略lambda匿名方法
                if (e.getName().startsWith("lambda$")) {
                    return;
                }
                MethodEntity method = new MethodEntity(e.getName(),
                        e.getReturnType().getSimpleName(),
                        "public",
                        Arrays.stream(e.getParameterTypes()).map(Class::getSimpleName).collect(Collectors.toList()),
                        false);
                classEntity.addMethod(method);
            });
            classEntities.add(classEntity);
        });
        return classEntities;
    }
}